
package biblio.service.aop.logging;


import java.lang.reflect.Method;
import java.util.Arrays;
import org.aopalliance.intercept.MethodInvocation;

import org.apache.log4j.Logger;


/**
 * Template of advice for logging.
 * 
 * @author mephisto
 */
public class UniversalAdviceTemplate
{
    public static void afterThrowing(LoggerLevel level, Method method, Object[] args,
            Object target, Exception e) throws Throwable
    {
        Logger log = Logger.getLogger(target.getClass());
        switch(level)
        {
            case WARN: log.warn(e);
            case ERROR: log.error(e);
            case INFO: log.info(e);
            case DEBUG: log.debug(e);
            case FATAL: log.fatal(e);
        }
    }

    public static void before(LoggerLevel level, Method method, Object[] args,
            Object target) throws Throwable
    {
        Class<?> cl = target.getClass();
        Logger log = Logger.getLogger(cl);
        StringBuffer sB = new StringBuffer(cl.getSimpleName()).append(
                "#").append(method.toGenericString()).append(
                ". args=").append(Arrays.toString(args));
        switch(level)
        {
            case WARN: log.warn(sB.toString());
            case ERROR: log.error(sB.toString());
            case INFO: log.info(sB.toString());
            case DEBUG: log.debug(sB.toString());
            case FATAL: log.fatal(sB.toString());
        }
    }

    public static void afterReturning(LoggerLevel level, Object returnValue,
            Method method, Object[] args, Object target) throws Throwable
    {
        Class<?> cl = target.getClass();
        Logger log = Logger.getLogger(cl);
        StringBuffer sB = new StringBuffer(cl.getSimpleName()).append(
                "#").append(method.toGenericString()).append(
                ". args=").append(Arrays.toString(args)).append(
                ". exit=return[").append(returnValue).append("]");
        switch(level)
        {
            case WARN: log.warn(sB.toString());
            case ERROR: log.error(sB.toString());
            case INFO: log.info(sB.toString());
            case DEBUG: log.debug(sB.toString());
            case FATAL: log.fatal(sB.toString());
        }
    }

    public static Object invoke(LoggerLevel level, MethodInvocation invocation) throws Throwable
    {
        Class<?> cl = invocation.getThis().getClass();
        Logger log = Logger.getLogger(cl);
        try
        {
            log.debug("Around before");
            StringBuffer sB = new StringBuffer(cl.getSimpleName()).append(
                "#").append(invocation.getMethod().toGenericString()).append(
                ". args=").append(Arrays.toString(invocation.getArguments())).append(
                ". exit=return[").append(invocation.proceed()).append("]");
            switch(level)
            {
                case WARN: log.warn(sB.toString());
                case ERROR: log.error(sB.toString());
                case INFO: log.info(sB.toString());
                case DEBUG: log.debug(sB.toString());
                case FATAL: log.fatal(sB.toString());
            }

            return invocation.proceed();
        }
        finally
        {
            log.debug("Around after");
        }
    }
}
